<!DOCTYPE html>
<html>
  <head>
     
    <meta charset="UTF-8">
    <title>操作系统2 - 测开、Java后端最常见、最核心的面试题总结</title>
    <link rel="shortcut icon" href="/static/img/icon.png">
    <link rel="icon" href="/static/img/icon.png" sizes="192x192"/>
    
<link rel="stylesheet" href="/static/kico.css">
<link rel="stylesheet" href="/static/hingle.css">

    
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

    <meta name="viewport" content="width=device-width, maximum-scale=1, initial-scale=1"/>
    <meta property="og:site_name" content="测开、Java后端最常见、最核心的面试题总结">
    <meta property="og:title" content="操作系统2"/>
    
<meta name="generator" content="Hexo 7.3.0"></head>

  <body>
    <header>
    <div class="head-title">
        <h4>测开、Java后端最常见、最核心的面试题总结</h4>
    </div>
    <div class="head-action">
        <div class="toggle-btn"></div>
        <div class="light-btn"></div>
        <div class="search-btn"></div>
    </div>
    <form class="head-search" method="post">
        <input type="text" name="s" placeholder="搜索什么？">
    </form>
    <nav class="head-menu">
        <a href="/">首页</a>
        
    </nav>
</header>

    <main>
    <div class="wrap min">
        <section class="post-title">
            <h2>操作系统2</h2>
            <div class="post-meta">
                <time class="date">2024.07.25</time>
            
            </div>
        </section>
        <article class="post-content">
        
            <h1><span id="18什么是死锁">18.什么是死锁？</span></h1><p>死锁是指在并发系统中，两个或多个进程或线程相互等待对方释放资源，从而导致这些进程或线程都无法继续执行的现象。这种状态会导致系统的部分资源被无限期地占用，无法完成预期的操作。</p>
<h1><span id="19死锁产生有哪些条件">19.死锁产生有哪些条件？</span></h1><p><strong>互斥条件</strong>：同一时间内仅有一个进程可以访问该资源。如果其他进程请求该资源，则必须等待，直到资源被释放。</p>
<p><strong>持有并等待条件：</strong>一个进程已经持有至少一个资源，并且又请求了新的资源，而该资源被其他进程持有，因此该进程必须等待。同时，它保持对自己已持有的资源的占用。</p>
<p><strong>不可剥夺条件</strong>：资源不能被强制剥夺，即资源只能由持有它的进程主动释放，而不能由其他进程强行剥夺。</p>
<p><strong>循环等待条件</strong>：存在一个进程集合，每个进程都在等待下一个进程所占有的资源，从而形成一个闭环的循环等待链。例如，进程A等待进程B所持有的资源，进程B等待进程C所持有的资源，而进程C又等待进程A所持有的资源。</p>
<h1><span id="20如何解决死锁问题">20.如何解决死锁问题？</span></h1><ol>
<li><p><strong>预防死锁</strong>：</p>
<ul>
<li><p>破坏死锁条件</p>
<p>：通过确保上述四个条件中的一个或多个不成立，从根本上预防死锁的发生。</p>
<ul>
<li><strong>破坏互斥条件</strong>：尽量避免资源的独占使用，比如使用可共享的资源。</li>
<li><strong>破坏持有并等待条件</strong>：在请求资源时要求进程不占用其他资源，或者在进程获得所有需要的资源之前不允许占用资源。</li>
<li><strong>破坏不剥夺条件</strong>：当一个进程无法获得所需资源时，强制释放它已持有的资源。</li>
<li><strong>破坏循环等待条件</strong>：通过强制进程按照某种顺序请求资源，避免形成循环等待。</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>避免死锁</strong>：</p>
<ul>
<li><strong>银行家算法</strong>：一种常用的避免死锁的算法，通过模拟资源分配过程，确保系统始终处于安全状态。只有当系统在分配完资源后仍能满足所有进程的需求时，才进行实际分配。</li>
</ul>
</li>
<li><p><strong>检测和恢复死锁</strong>：</p>
<ul>
<li><p><strong>死锁检测</strong>：系统定期检查是否存在死锁，常用的方法是构建资源分配图，检查是否存在环路。</p>
</li>
<li><p>死锁恢复</p>
<p>：如果检测到死锁，可以采取如下措施进行恢复：</p>
<ul>
<li><strong>资源剥夺</strong>：强制剥夺某个进程占用的资源，使其他进程能够继续执行。</li>
<li><strong>回滚</strong>：将某些进程回滚到之前的安全状态，释放资源。</li>
<li><strong>终止进程</strong>：终止一个或多个进程，以打破循环等待。</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>忽略死锁</strong>：</p>
<ul>
<li>某些系统（如大部分操作系统）选择简单地忽略死锁问题，假设死锁很少发生，并让用户或管理员来解决这种罕见的情况。</li>
</ul>
</li>
</ol>
<h1><span id="21活锁和饥饿锁是什么">21.活锁和饥饿锁是什么？</span></h1><p><strong>饥饿锁：</strong></p>
<p>饥饿锁是指某个进程或线程由于其他进程或线程长期占用资源而始终无法获得所需资源，从而无法继续执行的现象。饥饿锁可以看作是资源分配不公平造成的问题。</p>
<p><strong>活锁：</strong></p>
<p>活锁是指多个进程或线程在相互响应对方的动作时，不断改变状态或重试某个操作，结果导致它们始终无法推进到下一步。这些进程或线程虽然没有被阻塞，但由于它们不断地调整自己的状态以响应其他进程或线程的变化，导致系统无法取得进展。</p>
<p>活锁可以用两个人过一条很窄的小桥来比喻：为了让对方先过，两个人都往旁边让，但两个人总是让到同一边。这样，虽然两个人的状态一直在变化，但却都无法往前推进。</p>
<h1><span id="22什么是虚拟内存">22.什么是虚拟内存？</span></h1><p>虚拟内存是一种内存管理技术，它允许计算机在实际物理内存不足时，使用硬盘上的部分空间来扩展内存。通过虚拟内存，操作系统可以让应用程序认为它有一个连续的大内存空间，而实际上，这个内存空间可能部分在物理内存中，部分在硬盘上的虚拟内存文件中。</p>
<p>每个进程都有自己独立的地址空间，再由操作系统映射到到实际的物理内存。</p>
<p>于是，这⾥就引出了两种地址的概念：</p>
<p>程序所使⽤的内存地址叫做<strong>虚拟内存地址</strong></p>
<p>实际存在硬件⾥⾯的空间地址叫<strong>物理内存地址</strong>。</p>
<h1><span id="23什么是内存分段">23.什么是内存分段？</span></h1><p>程序是由若干个逻辑分段组成的，可由代码分段、数据分段、栈段、堆段组成。不同的段是有不同的属性的，所以就⽤分段的形式把这些段分离出来。</p>
<p>分段机制下的虚拟地址由两部分组成，段号和段内偏移量。</p>
<p>虚拟地址和物理地址通过段表映射，段表主要包括段号、段的界限。</p>
<h1><span id="24什么是内存分页">24.什么是内存分页？</span></h1><p>内存分页是一种内存管理技术，它将物理内存和虚拟内存分成固定大小的块，这些块称为“页”。分页的主要目的是高效地管理内存，减少内存碎片，并支持虚拟内存，使操作系统可以运行大于物理内存的程序。</p>
<p>访问分页系统中内存数据需要两次的内存访问 ：一次是从内存中访问页表，从中找到指定的物理页号，加上页内偏移得到实际物理地址，第二次就是根据第一次得到的物理地址访问内存取出数据。</p>
<h1><span id="25多级页表知道吗">25.多级页表知道吗？</span></h1><p>在简单的分页系统中，页面表用于将虚拟地址映射到物理地址。对于大型虚拟地址空间，单级页表可能非常庞大，占用大量内存空间。每个虚拟地址的页表项存储了该页对应的物理页框的地址。</p>
<p>多级页表将单级页表的内容层次化，通过多级页表结构来减少页表的大小。主要分为多个层次，每个层次的页表负责管理更小范围的虚拟地址空间。</p>
<h1><span id="26什么是快表">26.什么是快表？</span></h1><p>快表（TLB）是一种用于加速虚拟地址到物理地址转换的高速缓存，主要利用了局部性原理，通过缓存最近使用的地址映射，减少了内存访问的延迟和页表查找的开销，显著提高了虚拟内存系统的性能。快表一般是储存在CPU中，而不是内存或硬盘。</p>
<h1><span id="27分页和分段有什么区别">27.分页和分段有什么区别？</span></h1><ul>
<li>段是信息的逻辑单位，它是根据用户的需要划分的，因此段对用户是可见的 ；页是信息的物理单位，是为了管理主存的方便而划分的，对用户是透明的。</li>
<li>段的大小不固定，由它所完成的功能决定；页的大小固定，由系统决定</li>
<li>段向用户提供二维地址空间；页向用户提供的是一维地址空间</li>
<li>段是信息的逻辑单位，便于存储保护和信息的共享，页的保护和共享受到限制。</li>
</ul>
<h1><span id="28什么是交换空间">28.什么是交换空间？</span></h1><p>交换空间是一种在操作系统中使用的硬盘存储区域，用于暂时存放那些被操作系统从物理内存中移出的数据。交换空间主要用于扩展系统的虚拟内存容量，允许系统在物理内存不足时继续运行更多的程序或处理更多的数据。</p>
<p>交换空间可以看作是虚拟内存的一部分。当物理内存不足时，操作系统会将一些不常用的内存页（如长期未访问的数据）从RAM中移到交换空间，以腾出物理内存供当前正在运行的进程使用。</p>
<h1><span id="29什么是缺页中断">29.什么是缺页中断？</span></h1><p>缺页中断是虚拟内存管理的一个重要概念。当一个程序访问的页不在物理内存中时，就会发生缺页中断。操作系统需要从磁盘上的交换区或页面文件中将缺失的页调入内存。</p>
<h1><span id="30页面置换算法有哪些">30.页面置换算法有哪些？</span></h1><p>页面置换算法用于决定当物理内存已满时，应该将哪个页面从内存中移出（置换），以腾出空间给新的页面。这些算法在操作系统的虚拟内存管理中扮演着关键角色。常见的页面置换算法包括以下几种：</p>
<ol>
<li><p><strong>先进先出算法（FIFO, First-In, First-Out）</strong></p>
<ul>
<li><strong>概念</strong>：最早进入内存的页面最先被置换出去。FIFO使用一个队列来管理页面，当需要置换时，移出队列最前面的页面。</li>
<li><strong>优点</strong>：实现简单。</li>
<li><strong>缺点</strong>：不能有效地利用页面的使用情况，可能会导致常用页面被不合理地置换出内存。而且会有贝尔迪异常。</li>
</ul>
</li>
<li><p><strong>最近最少使用算法（LRU, Least Recently Used）</strong></p>
<ul>
<li><strong>概念</strong>：置换那些最近一段时间内最少被使用的页面，假设最近未被使用的页面未来也不大可能被使用。</li>
<li><strong>实现</strong>：通常使用栈或时间戳来记录页面的使用情况。</li>
<li><strong>优点</strong>：较FIFO更优，能够更好地反映页面的使用频率。</li>
<li><strong>缺点</strong>：实现复杂，需要额外的硬件支持或较高的时间开销来维护使用历史。</li>
</ul>
</li>
<li><p><strong>最不常用算法（LFU, Least Frequently Used）</strong></p>
<ul>
<li><strong>概念</strong>：置换访问频率最少的页面，假设访问频率低的页面未来也不会被频繁访问。</li>
<li><strong>实现</strong>：需要一个计数器来记录每个页面的访问次数。</li>
<li><strong>优点</strong>：适用于较为稳定的访问模式。</li>
<li><strong>缺点</strong>：不适用于访问模式变化较大的情况，容易导致“频率永久积累”问题，即频繁访问的旧页面即使不再被访问，也难以被置换。</li>
</ul>
</li>
<li><p><strong>最佳置换算法（OPT, Optimal Page Replacement）</strong></p>
<ul>
<li><strong>概念</strong>：置换将来最长时间不会被访问的页面。这是一种理论上最优的算法，可以达到最少的缺页率。</li>
<li><strong>实现</strong>：OPT是基于对未来的访问模式有完全了解的前提下进行的，因此在实际中无法实现，但常用于分析和比较其他算法的性能。</li>
<li><strong>优点</strong>：能够保证最小的缺页次数。</li>
<li><strong>缺点</strong>：不可实现，因为无法预知未来。</li>
</ul>
</li>
<li><p><strong>时钟算法</strong></p>
<ul>
<li><strong>概念</strong>：是一种改进的FIFO算法，为每个页面设置一个使用标志位。当需要置换页面时，检查页面的使用标志位，如果为0（表示未被最近使用过），则置换该页面；如果为1，则将其重置为0并跳过，继续检查下一个页面。</li>
<li><strong>实现</strong>：通常用一个指针以循环方式遍历页面集合，类似于时钟的指针，因此得名时钟算法。</li>
<li><strong>优点</strong>：简单易实现，避免了FIFO算法中常用页面被置换的问题。</li>
<li><strong>缺点</strong>：虽然性能好于FIFO，但仍可能不是最优选择。</li>
</ul>
</li>
<li><p><strong>增强型时钟算法</strong></p>
<ul>
<li><strong>概念</strong>：是在时钟算法的基础上，增加了对页面修改标志位的检查。页面置换时优先选择那些没有被修改且最近未被使用的页面。</li>
<li><strong>优点</strong>：减少了对修改页面的置换，降低了系统的写回开销。</li>
<li><strong>缺点</strong>：实现比基本时钟算法复杂。</li>
</ul>
</li>
</ol>
<h1><span id="31硬链接和软链接有什么区别">31.硬链接和软链接有什么区别？</span></h1><p><strong>硬链接</strong></p>
<p>硬链接是文件系统中的一个实际文件引用，也就是说，不同的硬链接指向的是相同的文件数据块。创建硬链接实际上是在文件系统中给文件增加一个新的目录项（即文件名）。所有硬链接共享相同的 inode 号码（即指向文件数据块的指针），因此它们等价于原文件。</p>
<p>特点：</p>
<ol>
<li>文件数据共享：硬链接和原文件的数据完全相同，它们指向相同的数据块，因此修改任何一个硬链接会影响所有链接。</li>
<li>不影响原文件的删除：删除硬链接不会删除文件的实际数据，只有当所有指向文件的硬链接都被删除后，文件数据才会被释放。</li>
<li>同一文件系统：硬链接只能在同一个文件系统内创建，不能跨文件系统。</li>
<li>不能链接目录：一般情况下，硬链接不能用于目录，主要是为了防止文件系统结构混乱。</li>
</ol>
<p><strong>软链接</strong></p>
<p>软链接是一种特殊类型的文件，它包含一个指向另一个文件或目录的路径。它类似于 Windows 中的快捷方式，软链接本身是一个独立的文件，存储的是目标文件的路径。</p>
<p>特点：</p>
<ol>
<li>指向路径：软链接指向的是文件或目录的路径，而不是文件数据本身。因此，软链接的大小是路径的长度，而不是目标文件的大小。</li>
<li>可跨文件系统：软链接可以指向不同文件系统中的文件或目录。</li>
<li>链接目录：软链接可以指向目录，这使得它在文件组织和管理中非常灵活。</li>
<li>目标文件删除后：如果删除了软链接指向的原文件，软链接会变成一个“断开的链接”（即无效链接），但软链接本身仍然存在。</li>
</ol>
<h1><span id="32零拷贝了解吗">32.零拷贝了解吗？</span></h1><p><strong>零拷贝</strong>是一种计算机操作技术，主要用于减少在数据传输过程中内存拷贝的次数，从而提高效率和减少 CPU 使用率。在传统的 I&#x2F;O 操作中，数据通常需要在用户空间和内核空间之间多次拷贝，而零拷贝技术通过直接在内核空间中处理数据，避免了这些不必要的拷贝，减少用户态与内核态的上下文切换。</p>
<p>零拷贝技术实现主要有两种：</p>
<ol>
<li><code>sendfile</code> 系统调用</li>
</ol>
<p><code>sendfile</code> 是 Linux 操作系统中最常用的零拷贝技术之一，特别适用于将数据从磁盘文件直接发送到网络的场景。</p>
<ul>
<li>在使用 <code>sendfile</code> 时，数据直接从磁盘读取到内核空间，然后通过内核直接发送到网络接口，而不需要中间的数据拷贝到用户空间。这使得数据从磁盘到网络接口的传输过程只需要一次拷贝（从内核缓冲区到网络接口），减少了 CPU 开销。</li>
</ul>
<ol start="2">
<li><code>mmap</code> 和 <code>write</code> 组合</li>
</ol>
<p>另一种常见的零拷贝技术是通过 <code>mmap</code> 和 <code>write</code> 系统调用组合使用。</p>
<ul>
<li><code>mmap</code> 将文件映射到用户空间的内存中，使得应用程序可以直接访问文件的内容，而不需要显式的数据拷贝。随后，通过 <code>write</code> 系统调用可以将数据直接从用户空间写入文件中，减少了中间的拷贝步骤。</li>
</ul>
<h1><span id="33聊聊阻塞与非阻塞-io-同步与异步-io">33.聊聊阻塞与非阻塞 IO、 同步与异步 IO？</span></h1><ul>
<li><p><strong>阻塞 I&#x2F;O</strong><br>当应用程序发起 I&#x2F;O 操作（如读或写）时，如果数据尚未准备好，操作系统会让该进程进入<strong>阻塞状态</strong>。在这种状态下，进程会停止运行，等待数据准备好或者操作完成后再继续执行。</p>
</li>
<li><p><strong>非阻塞 I&#x2F;O</strong><br>非阻塞 I&#x2F;O 是阻塞 I&#x2F;O 的一种改进：当应用程序发起 I&#x2F;O 操作时，如果数据尚未准备好，操作系统立即返回一个状态值，告诉应用程序数据还不可用。应用程序不会被阻塞，可以继续执行其他任务。</p>
</li>
<li><p><strong>基于非阻塞的 I&#x2F;O 多路复用</strong><br>在非阻塞 I&#x2F;O 中，应用程序需要不断地轮询某个 I&#x2F;O 操作是否准备好。这种反复检查的过程虽然避免了进程被阻塞，但也带来了新的问题：应用程序在轮询过程中会频繁地占用 CPU 资源，这可能导致性能问题，尤其是在高并发的场景下。所以引入了<strong>I&#x2F;O 多路复用</strong>技术。常见的 I&#x2F;O 多路复用机制：</p>
<ul>
<li><strong><code>select</code> 系统调用</strong>：<br><code>select</code> 是一种早期的 I&#x2F;O 多路复用机制。应用程序可以将它想要监视的多个文件描述符传递给 <code>select</code>，然后 <code>select</code> 会在这些文件描述符中等待，直到至少有一个文件描述符的状态发生变化（如变为可读或可写）。这时，<code>select</code> 返回，并告诉应用程序哪个文件描述符已经准备好进行 I&#x2F;O 操作。缺点是，当监视的文件描述符数量很大时，<code>select</code> 的性能会下降。</li>
<li><strong><code>poll</code> 系统调用</strong>：<br><code>poll</code> 与 <code>select</code> 类似，但它没有文件描述符数量的限制，并且在性能和接口上有一些改进。它使用一个结构体数组来传递多个文件描述符。与 <code>select</code> 一样，<code>poll</code> 也会等待，直到有一个或多个文件描述符准备好进行 I&#x2F;O 操作。但 <code>poll</code> 的问题与 <code>select</code> 类似，当监视大量文件描述符时，性能依然不是最佳的。</li>
<li><strong><code>epoll</code> 系统调用</strong>：<ul>
<li>epoll 在内核里使用<strong>红黑树</strong>来跟踪进程所有待检测的⽂件描述字，把需要监控的文件描述符加入内核中的红黑树里，红黑树是个高效的数据结构，增删改查的时间复杂度是 O(logn) ，通过对这棵红黑树进行操作，这样就不需要像 select&#x2F;poll 每次操作时都传⼊整个文件描述符集合，只需要传入一个待检测的文件描述符，减少了内核和用户空间大量的数据拷贝和内存分配。</li>
<li>第⼆点， epoll 使用事件驱动的机制，内核里维护了⼀个<strong>链表</strong>来记录就绪事件，当某个文件描述符的状态发生变化时，通过回调函数，内核会将其加入到这个就绪事件链表中，当用户调⽤ epoll_wait() 函数时，只会返回状态发生变化的⽂件描述符，不需要像 select&#x2F;poll 那样轮询扫描整个文件描述符集合，大大提高了检测的效率。</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>同步I&#x2F;O</strong><br>之前的几种都是同步I&#x2F;O。在同步 I&#x2F;O 模型中，无论 I&#x2F;O 操作是阻塞还是非阻塞，应用程序都必须等待数据传输完成后，才能继续处理后续操作。</p>
</li>
<li><p><strong>异步 I&#x2F;O</strong><br>在异步 I&#x2F;O 模型中，应用程序发起 I&#x2F;O 操作后，操作系统会立即返回，应用程序可以继续执行其他任务，而无需等待 I&#x2F;O 操作的完成。当 I&#x2F;O 操作完成后，操作系统会通知应用程序（通常通过回调函数或信号），此时应用程序才会处理已完成的 I&#x2F;O 操作。</p>
</li>
</ul>

        </article>
        <section class="post-near">
            <ul>
                
                    <li>上一篇: <a href="/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C2/">计算机网络2</a></li>
                
                
                    <li>下一篇: <a href="/JUC2/">JUC 2</a></li>
                
            </ul>
        </section>
        
    
        <section class="post-author">
        
            <figure class="author-avatar">
                <img src="https://sdn.geekzu.org/avatar/d22eb460ecab37fcd7205e6a3c55c228?s=200&r=X&d=" alt="Hingle" />
            </figure>
        
            <div class="author-info">
                <h4>Hingle</h4>
                <p>请在这里设置你的作者信息</p>
            </div>
        </section>
    
    </div>
</main>

    <footer>
    <div class="buttons">
        <a class="to-top" href="#"></a>
    </div>
    <div class="wrap min">
        <section class="widget">
            <div class="row">
                <div class="col-m-4">
                    <h3 class="title-recent">最新文章：</h3>
                    <ul class="post-list"><li class="post-list-item"><a class="post-list-link" href="/%E9%A1%B9%E7%9B%AE/">项目</a></li><li class="post-list-item"><a class="post-list-link" href="/MySQL2/">MySQL2</a></li><li class="post-list-item"><a class="post-list-link" href="/Java17%E6%96%B0%E7%89%B9%E6%80%A7/">Java17新特性</a></li><li class="post-list-item"><a class="post-list-link" href="/Redis2/">Redis2</a></li><li class="post-list-item"><a class="post-list-link" href="/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C2/">计算机网络2</a></li><li class="post-list-item"><a class="post-list-link" href="/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F2/">操作系统2</a></li></ul>
                </div>
            </div>
        </section>
        <section class="sub-footer">
            <p>© 2024 <a href="/">测开、Java后端最常见、最核心的面试题总结</a>. All Rights Reserved. Theme By <a href="https://github.com/Dreamer-Paul/Hingle" target="_blank" rel="nofollow">Hingle</a>.</p>
        </section>
    </div>
</footer>


<script src="/static/kico.js"></script>
<script src="/static/hingle.js"></script>


<script>var hingle = new Paul_Hingle({"copyright":false,"night":false});</script>

  </body>
</html>
